package com.gitee.wsl.coroutines.collections

import com.gitee.wsl.collections.queue.Queue
import kotlinx.atomicfu.AtomicRef
import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.loop

//interface Queue<T> {
//    fun poll(): T?
//
//    fun enqueue(value: T)
//
//    fun peek(): T?
//
//    fun isEmpty(): Boolean
//}

//interface MutableQueue<E> : Queue<E> {
//    val size: Int
//
//    fun add(var1: E): Boolean
//
//    override fun enqueue(value: E) {
//        add(value)
//    }

    //fun offer(var1: E): Boolean = add(var1)

//    fun addAll(elements: Collection<E>): Boolean
//
//    fun clear()
//
//    fun remove(element: E): Boolean
//
//    fun removeAll(c: Collection<E>): Boolean
//
//    operator fun contains(element: E): Boolean
//
//    fun containsAll(elements: Collection<E>): Boolean

//}


class ConcurrentQueue<T : Any>() : Queue<T> {

    override val size: Int
        get() = throw NotImplementedError()

    /**
     * Dummy node used to initialize the head and tail pointers
     */
    private val dummy = Node<T?>(null)

    /**
     * Initially points to the dummy node and is updated atomically
     */
    private val head: AtomicRef<Node<T?>> = atomic(dummy)

    /**
     * Initially points to the dummy node and is updated atomically
     */
    private val tail: AtomicRef<Node<T?>> = atomic(dummy)

    private class Node<T>(val value: T) {
        val next = atomic<Node<T>?>(null)
    }

    /*override fun enqueue(value: T) {*/
    override fun add(element: T):Boolean {
        val node: Node<T?> = Node(element)
        tail.loop { curTail ->
            val curNext = curTail.next.value
            if (curNext != null) {
                tail.compareAndSet(curTail, curNext)
                return@loop
            }
            if (curTail.next.compareAndSet(null, node)) {
                tail.compareAndSet(curTail, node)
                return true
            }
        }
    }

    override fun pollOrNull(): T?  {
        head.loop { curHead ->
            val next = curHead.next.value ?: return null
            if (head.compareAndSet(curHead, next)) return next.value
        }
    }

    /**
     * Returns the value at the head of the queue without removing it.
     * @return the value at the front of the queue, or null if the queue is empty.
     */
    override fun peekOrNull(): T? = head.value.next.value?.value

    /**
     * Checks if the queue is empty.
     * @return true if the queue is empty, false otherwise.
     */
    override fun isEmpty(): Boolean = head.value == tail.value && head.value.next.value == null

    override fun clear() {
        tail.value = dummy
        head.value = dummy
    }

    override fun remove(element: T): Boolean {
       throw NotImplementedError()
    }

    override fun contains(element: T): Boolean {
        throw NotImplementedError()
    }

    override fun iterator(): MutableIterator<T> {
        throw NotImplementedError()
    }
}